/**
 * representation of Erzeuger (has runs instead of outputStorage)
 * @author Lukas Koell
 * @author Johannes Riedmann
 * @author David Medenjak
 */

public class Erzeuger extends Thread {

    /** name of the Erzeuger (e.g. Wildschweinjaeger1, ..) */
    protected String name;
    /** storage the worker is putting his produce into */
    protected final Lager outputStorage;
    /** how long the worker needs to finish his work */
    protected int workDuration;
    /** number of units the worker produced */
    protected int producedResources;
    /** number of unites the worker is producing */
    private int produceCount;
    /** how much does the worker produce in 1 cycle */
    protected int outAmount;
    /** number of runs the Erzeuger has to accomplish */
    protected boolean run;

    public Erzeuger(String name, Lager outputStorage, int produceCount) {
        this.outputStorage = outputStorage;
        workDuration = (int) (Math.random() * 100) % 50;
        this.produceCount = produceCount;
        this.name = name;
        this.run = true;
    }

    /**
     * @return amount of units the worker puts into outputStorage
     */
    public int getOutAmount() {
        return outAmount;
    }

    /**
     * if worker gets fired, status message is printed
     */
    protected void terminate() {
        System.out.println(name + " produced "
                + this.producedResources + " units (" + workDuration + "ms per unit)");
    }

    @Override
    public void run() {
        while (run) {
            if (this.isInterrupted()) {
                terminate();
                run = false;
                return;
            }

            // arbeiten
            try {
                Thread.sleep(workDuration);
            } catch (InterruptedException e) {
                terminate();
                run = false;
                return;
            }

            depositRessources();
        }
    }

    /**
     * units of the worker are placed in the storage
     */
    protected void depositRessources() {
        int deposited = 0;
        synchronized (outputStorage) {
            while (deposited < produceCount) {
                while (!outputStorage.canInsert()) {
                    try {
                        outputStorage.wait();
                    } catch (InterruptedException ex) {
                        this.producedResources += deposited;
//                        System.out.println(name + " got fired and lets "
//                                + (produceCount - deposited) + " items drop to the ground.");
                        terminate();
                        run = false;
                        return;
                    }
                }
                deposited += outputStorage.insert(produceCount - deposited);
//                System.out.println(name + " now has deposited " + deposited + "/" + produceCount);
            }
        }
        this.producedResources += deposited;
    }
}
